package spoon.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import spoon.core.domain.Game;

@Service
@Qualifier("sbobetFootballService")
public class SbobetFootballService extends SbobetAbstractService {

	@Resource(name = "sbobet.football.league")
	protected void getLeagueMap(Map<String, String> map) {
		this.leagueMap = map;
	}

	@Resource(name = "sbobet.football.team")
	protected void getTeamMap(Map<String, String> map) {
		this.teamMap = map;
	}

	@Value("#{sbobet['football.itemCode']}")
	protected void getItemCode(String itemCode) {
		this.ITEM_CODE = itemCode;
	}

	@Value("#{sbobet['football.itemName']}")
	protected void getItemName(String itemName) {
		this.ITEM_NAME = itemName;
	}

	@Value("#{sbobet['football.url']}")
	protected void getGateUrl(String url) {
		this.GATE_URL = url;
	}

	@Override
	public List<Game> getLinkList() {
		log.info("===================================================================");
		log.info("    {} {} 리그 정보 검색 시작", SITE, ITEM_CODE);

		List<Game> linkList = new ArrayList<Game>();
		int gameCnt = 0;

		// 오늘 경기
		Elements elements = httpService.getElements(GATE_URL, "script");

		// dynamic script (nation, league)
		setDynamic(elements.select("[src*=euro-dynamic.js]").attr("src"));
		// static script (sub betting type)
		setStatic(elements.select("[src*=euro-static.js]").attr("src"));
		// template script (betting type)
		setTemplate(elements.select("[src*=euro-template.js]").attr("src"));

		Pattern p = Pattern.compile(PATTERN_LINK);
		Matcher m = p.matcher(elements.last().toString());

		while (m.find()) {
			Game link = new Game();
			link.setSite(SITE);
			link.setUrl(URL);
			link.setItemCode(ITEM_CODE);
			link.setItemName(ITEM_NAME);
			getLinkInfo(link, m.group());
			linkList.add(link);
			gameCnt++;
		}
		
		// 내일경기
		elements = httpService.getElements(GATE_URL + "/" + getDate(1), "script");
		m = p.matcher(elements.last().toString());

		while (m.find()) {
			Game link = new Game();
			link.setSite(SITE);
			link.setUrl(URL);
			link.setItemCode(ITEM_CODE);
			link.setItemName(ITEM_NAME);
			getLinkInfo(link, m.group());
			linkList.add(link);
			gameCnt++;
		}

		log.info("    {} {} 리그 정보 검색 종료. 전체 추가 게임수 = {}", SITE, ITEM_CODE, gameCnt);
		log.info("===================================================================");

		return linkList;
	}

	@Override
	@Async
	public void getGame(Game link) {
		long startTime = System.currentTimeMillis();
		int bettingCnt = 0;

		// 게임별 상세 베팅 가져오기
		this.getBetting(link);

		// 데이터 입력
		if (link.getGameList().size() > 0) {
			bettingCnt = addBetting(link);
		}

		log.info("사이트: {}, 종목: {}, 국가: {}, 리그: {}, 팀명: {} vs {}, 베팅수: {}, 소요시간: {}초", SITE, ITEM_CODE, link.getNation(), link.getLeagueName(),
				link.getHomeTeamName(), link.getAwayTeamName(), bettingCnt, (System.currentTimeMillis() - startTime) / 1000.0f);
	}

	/**
	 * 게임정보를 저장하고 베팅정보를 가져온다.
	 * 
	 * @param game
	 */
	private void getBetting(Game game) {

		Elements elements = httpService.getElements(game.getLink(), "script");

		String data = elements.last().toString();

		Pattern p = Pattern.compile(PATTERN_DATA);
		Matcher m = p.matcher(data);

		while (m.find()) {
			getBetting(game, m.group(1));
		}
	}

	/**
	 * 베팅정보로 부터 베팅을 구해서 게임에 담는다.
	 * 
	 * @param game
	 * @param data
	 */
	private void getBetting(Game game, String data) {

		// 베팅정보와 배당을 뽑자
		Pattern p = Pattern.compile("\\[([0-9]+),([^\\]]+)\\],\\[([^\\]]+)\\]");
		Matcher m = p.matcher(data);

		if (!m.find())
			return;

		// Odd/Even Correct Score는 가져가지 않는다.
		int code = Integer.parseInt(m.group(1));
		if (code == 2 || code == 4 || code == 6 || code == 10 || code == 12 || code == 13 || code == 14) {
			return;		
		}
		
		Map<String, String> map = getBetType(m.group(2));
		map.put("handi", m.group(3));
		
		if (code == 1) { // Asian Handicap
			map.put("betTarget", "Goals");
			map.put("betTime", "FT");
			map.put("betType", "H");
			betHandicap(game, map);			
		} else if (code == 3) { // Over Under
			map.put("betTarget", "Goals");
			map.put("betTime", "FT");
			map.put("betType", "OU");
			betOverUnder(game, map);	
		} else if (code == 5) { // 1X2
			map.put("betTarget", "Goals");
			map.put("betTime", "FT");
			map.put("betType", "1X2");
			betMatch(game, map);	
		} else if (code == 7) { // First Half Asian Handicap
			map.put("betTarget", "Goals");
			map.put("betTime", "1H");
			map.put("betType", "H");
			betHandicap(game, map);	
		} else if (code == 8) { // First Half 1X2
			map.put("betTarget", "Goals");
			map.put("betTime", "1H");
			map.put("betType", "1X2");
			betMatch(game, map);	
		} else if (code == 9) { // First Half Over Under
			map.put("betTarget", "Goals");
			map.put("betTime", "1H");
			map.put("betType", "OU");
			betMatch(game, map);
		} else if (code == 11) { // Money Line
			log.error("{} ==================================================================, {}, {}", "Money Line", game.getHomeTeamName(), game.getAwayTeamName());
			// TODO
		} else if (code == 15) { // Double Chance
			map.put("betTarget", "Goals");
			map.put("betTime", "FT");
			map.put("betType", "DC");
			betMatch(game, map);
		} else if (code == 16) { // Asian 1X2
			log.error("{} ==================================================================, {}, {}", "Asian 1X2", game.getHomeTeamName(), game.getAwayTeamName());
			// TODO
		} else if (code == 17) { // First Half Asian 1X2
			log.error("{} ==================================================================, {}, {}", "First Half Asian 1X2", game.getHomeTeamName(), game.getAwayTeamName());
			// TODO
		} else if (code > 99) { // spacial
			if ("Total Corner".equals(map.get("subType"))) {
				map.put("betTarget", "Corner");
				code = Integer.parseInt(map.get("subCode"));

				if (code == 5) { // 1X2
					map.put("betTime", "FT");
					map.put("betType", "1X2");
					betMatch(game, map);
				} else if (code == 8) { // First Half 1X2
					map.put("betTime", "1H");
					map.put("betType", "1X2");
					betMatch(game, map);	
				} else if (code == 1) { // Asian Handicap
					map.put("betTime", "FT");
					map.put("betType", "H");
					betHandicap(game, map);		
				} else if (code == 7) { // First Half Asian Handicap
					map.put("betTime", "1H");
					map.put("betType", "H");
					betHandicap(game, map);	
				} else if (code == 3) { // Over Under
					map.put("betTime", "FT");
					map.put("betType", "OU");
					betOverUnder(game, map);	
				} else if (code == 9) { // First Half Over Under
					map.put("betTime", "1H");
					map.put("betType", "OU");
					betMatch(game, map);
				} else {
					log.error("########################## 스페셜 구현되지 않은 코드 : {}, {}, {}", code, game.getHomeTeamName(), game.getAwayTeamName());
				}
			}
		}

		// log.info("{}", m.group());
		// log.info("betType = {}, subType = {}, handi = {}, 배당 = {}", map.get("betName"), map.get("subType"), map.get("handi"), m.group(3));
	}

}
